﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;

namespace Acms.AcmsControls
{
    [Serializable]
    public class AcmsContext : ISerializable
    {
        public AcmsContext()
        {
        }

        protected AcmsContext(SerializationInfo info, StreamingContext context)
        {
            this._TemplatePath = info.GetString("TemplatePath");
            this.SiteId = info.GetInt32("SiteId");
            this.PostId = info.GetInt32("PostId");
            this.PostGuid =  (Guid)info.GetValue("PostGuid", typeof(Guid));
            this.SiteVersion = info.GetValue("SiteVersion", typeof(DateTime?)) as DateTime?;
            this.IsLive = info.GetBoolean("IsLive");
            this.TemplateFileName = info.GetString("TemplateFileName");
            this.PostUrl = info.GetString("PostUrl");
            this.OriginalUrl = info.GetString("OriginalUrl");
        }

        public AcmsContext(string siteUrl, bool admin, string path, DateTime? siteVersion, bool isLive, string templateName, string originalUrl)
        {
            Acms.Bll.Post currentPost = null;
            if (!admin)
            {
                currentPost = Acms.Bll.Post.GetBySiteUrlAndPath(siteUrl, path, siteVersion);
            }
            if (currentPost != null)
            {
                LoadFromPost(currentPost, templateName);
            }
            else
            {
                Acms.Bll.Site site = Acms.Bll.Site.GetByRootUrl(siteUrl);
                if(site != null)
                {
                    LoadFromSite(site);
                }
            }
            this.OriginalUrl = originalUrl;
            this.SiteRoot = siteUrl;
        }

        public AcmsContext(Acms.Bll.Post currentPost, string templateName)
        {
            if (currentPost != null)
            {
                LoadFromPost(currentPost, templateName);
            }
        }

        private void LoadFromPost(Acms.Bll.Post currentPost, string templateName)
        {
            _CurrentPost = currentPost;

            SiteId = currentPost.SiteId;
            PostId = currentPost.Id;
            PostGuid = currentPost.PostGuid;
            SiteVersion = currentPost.SiteVersion;
            TemplateFileName = templateName;
            PostUrl = currentPost.Url;
        }

        private void LoadFromSite(Acms.Bll.Site site)
        {
            this.SiteId = site.Id;
            this.site = site;
        }

        private Acms.Bll.Post _CurrentPost;
        public Acms.Bll.Post CurrentPost
        {
            get 
            {
                if (_CurrentPost == null && PostId > 0)
                {
                    _CurrentPost = Acms.Bll.Post.GetById(SiteId, PostId, SiteVersion);
                }
                return _CurrentPost;
            }
        }

        public int SiteId { get; private set; }
        private Acms.Bll.Site site;
        public Acms.Bll.Site Site
        {
            get
            {
                if (site == null && SiteId > 0)
                {
                    site = Acms.Bll.Site.GetById(SiteId);
                }
                return site;
            }
        }
        public string SiteRoot { get; private set; }
        public int PostId { get; private set; }
        public Guid PostGuid { get; private set; }
        public DateTime? SiteVersion { get; private set; }
        public bool IsLive { get; private set; }
        public string TemplateFileName { get; private set; }
        public string PostUrl { get; private set; }
        public string OriginalUrl { get; private set; }
        
        private string _TemplatePath;
        public string TemplatePath
        {
            get
            {
                if (string.IsNullOrEmpty(_TemplatePath) && CurrentPost != null)
                {
                    Acms.Bll.TemplateFile templateFile = null;
                    if (!string.IsNullOrEmpty(TemplateFileName))
                    {
                        templateFile = CurrentPost.GetFile(TemplateFileName);
                        if (templateFile == null)
                        {
                            throw new Acms.Exceptions.TemplateException(string.Format("Could not load template file '{0}' for post '{1}' template '{2}'", TemplateFileName, CurrentPost.Path, CurrentPost.TemplateName));
                        }
                    }
                    else
                    {
                        templateFile = CurrentPost.GetDefaultFile();
                        if (templateFile == null)
                        {
                            throw new Acms.Exceptions.TemplateException(string.Format("Could not load default template file for post '{0}' template '{1}'", CurrentPost.Path, CurrentPost.TemplateName));
                        }
                    }
                    _TemplatePath = templateFile.Path;
                }
                return _TemplatePath;
            }
        }
        
        public string TemplateUrl
        {
            get
            {
                if (TemplatePath != null && TemplatePath.ToLower().EndsWith(".ascx"))
                {
                    return "~/LoadTemplate.aspx";
                }
                else
                {
                    return TemplatePath;
                }
            }
        }

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("TemplatePath", _TemplatePath);
            info.AddValue("PostId", this.PostId);
            info.AddValue("PostGuid", this.PostGuid);
            info.AddValue("SiteId", this.SiteId);
            info.AddValue("SiteVersion", this.SiteVersion);
            info.AddValue("TemplateFileName", this.TemplateFileName);
            info.AddValue("PostUrl", PostUrl);
            info.AddValue("OriginalUrl", OriginalUrl);
            info.AddValue("IsLive", this.IsLive);
        }

        #endregion

        internal static AcmsContext GetDummy(Random rnd)
        {
            AcmsContext tmp = new AcmsContext();
            tmp._CurrentPost = new Bll.DummyPost(rnd);
            tmp.PostId = 1;
            tmp.OriginalUrl = "#";
            tmp.PostUrl = "#";
            tmp.SiteId = 1;
            tmp.SiteVersion = null;
            return tmp;
        }

        internal void Refresh()
        {
            this._CurrentPost = null;
            this.site = null;
        }

        public string GetUrl(string relativePath, string templateName)
        {
            if (relativePath.StartsWith("~/AcmsFile/"))
            {
                return relativePath;
            }
            else
            {
                StringBuilder tmp = new StringBuilder();
                tmp.Append(relativePath);
                if (relativePath == "~")
                {
                    tmp.Append("/default.aspx");
                }
                string spacer = "?";
                if (SiteVersion == null || SiteVersion.Value >= DateTime.Now)
                {
                    if (tmp.ToString().Contains("?"))
                    {
                        spacer = "&";
                    }
                    if (SiteVersion == null)
                    {
                        tmp.AppendFormat("{0}AcmsSV=Pending", spacer);
                    }
                    else if (SiteVersion.Value > DateTime.Now)
                    {
                        tmp.AppendFormat("{1}AcmsSV={0}", System.Web.HttpUtility.UrlEncode(SiteVersion.Value.ToString("yyyy/MM/dd HH:mm")), spacer);
                    }
                    spacer = "&";
                }
                if (!string.IsNullOrEmpty(templateName))
                {
                    if (spacer != "&" && tmp.ToString().Contains("?"))
                    {
                        spacer = "&";
                    }
                    tmp.AppendFormat("{0}AcmsTF={1}", spacer, templateName);
                }
                return tmp.ToString();
            }
        }

        public string GetUrl(string relativePath)
        {
            return GetUrl(relativePath, null);
        }

        public string ResolveUrl(string relativePath, TemplatePage page)
        {
            return ResolveUrl(relativePath, null, page);
        }

        public string ResolveUrl(string relativePath, string templateName, TemplatePage page)
        {
            return page.ResolveUrl(GetUrl(relativePath, templateName));
        }

        public string FullyQualifiedUrl(string relativePath, TemplatePage page)
        {
            return FullyQualifiedUrl(relativePath, null, page);
        }

        public string FullyQualifiedUrl(string relativePath, string templateName, TemplatePage page)
        {
            return string.Concat("http://", page.Request.ServerVariables["Server_Name"], page.ResolveUrl(GetUrl(relativePath, templateName)));
        }

        public void EnsureLoggedIn(TemplatePage page)
        {
            if (!page.Request.IsAuthenticated)
            {
                RedirectToLoginPage(page);
            }
        }

        public void RedirectToLoginPage(TemplatePage page)
        {
            StringBuilder url = new StringBuilder();
            url.Append(System.Web.Security.FormsAuthentication.LoginUrl);
            if (System.Web.Security.FormsAuthentication.LoginUrl.Contains("?"))
            {
                url.Append("&");
            }
            else
            {
                url.Append("?");
            }
            url.Append("ReturnUrl=");
            if (CurrentPost != null)
            {
                url.Append(page.Server.UrlEncode(CurrentPost.Url));
            }
            else
            {
                url.Append(page.Server.UrlEncode(this.OriginalUrl));
            }
            page.Response.Redirect(GetUrl(url.ToString()), true);
        }

        public void RedirectToPost(Acms.Bll.Post post, TemplatePage currentPage)
        {
            currentPage.Response.Redirect(post.Url, true);
        }

        public void RedirectToPost(Acms.Bll.Post post, string templateFileName, TemplatePage currentPage)
        {
            currentPage.Response.Redirect(post.GetUrl(templateFileName), true);
        }

        public void SetSite(Acms.Bll.Site value)
        {
            this.site = value;
        }

        /// <summary>
        /// Redirects to the relative url 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="currentPage"></param>
        public void RedirectToUrl(string url, TemplatePage currentPage)
        {
            currentPage.Response.Redirect(currentPage.ResolveUrl(GetUrl(url)));

        }

    }

}
